#include "oscilloscope.h"
#include "adc.h"
#include "tim.h"
#include "gui.h"
#include <math.h>

uint8_t show_flag = 0; // 处理完成标志位
uint8_t show_normal_flag = 0; // NORMAL模式刷新标志
uint16_t show_points_num = 128; // 显示点数

uint16_t hor_pos = 0; // 水平位置
uint16_t trig_pos = 0; // 触发位置
int16_t trig_level = 3500; // 触发电平 [0-4095]

uint32_t period; // 周期 us
uint32_t frequency; // 频率 Hz
uint32_t V_max; // 最大值 mV
uint32_t V_min; // 最小值 mV
uint32_t V_pp; // 峰峰值 mV
double V_rms; // 有效值 mV

static RunState run_state; // 运行状态
static TrigMode trig_mode; // 触发模式

uint16_t sample_value[OSC_SAMPLE_NUM]; // 示波器采样数据
uint16_t show_value[OSC_SAMPLE_NUM]; // 显示数据
uint16_t stop_show_value[OSC_SAMPLE_NUM]; // 暂停时显示的数据

uint16_t show_trig_level;
uint16_t show_trig_level_mV;

uint16_t hor_arr_list[7] = {250, 100, 50, 25, 10, 5, 2};
int16_t hor_index = 2;

uint8_t is_measure = 0;

/**
 * @brief 示波器初始化函数
 */
void osc_init() {
    gui_startup();

    HAL_ADC_Start_DMA(&hadc1, (uint32_t *) sample_value, OSC_SAMPLE_NUM);
    __HAL_DMA_DISABLE_IT(hadc1.DMA_Handle, DMA_IT_HT);

    for (int i = 0; i < 3; i++) {
        HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
        HAL_Delay(500);
        HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
        HAL_Delay(500);
    }

    HAL_TIM_Base_Start(&htim3);
}

/**
 * @brief ADC转换完成回调函数
 * @details 会在完成全部点采样后被调用
 * @param hadc
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
    HAL_TIM_Base_Stop(&htim3);
    // 触发
    uint8_t cnt = 0;
    uint16_t t[2];

    double rms_sum = 0;
    double scaled_value;

    V_max = 0;
    V_min = 3300;
    for (int i = 1; i < OSC_SAMPLE_NUM; i++) {
        if (cnt <= 1 && sample_value[i - 1] < trig_level && sample_value[i] > trig_level) { // 触发
            if(cnt == 0) // 第一次触发
            {
                t[cnt] = i; // 记录触发时间

                trig_pos = i; // 记录触发位置，后续平移波形
                if (trig_mode == TM_NORMAL || (trig_mode == TM_SINGLE && run_state == OSC_RUN)) {
                    run_state = OSC_RUN;
                    show_normal_flag = 1;
                }
            }
            else if (cnt == 1) { // 第二次触发
                t[cnt] = i; // 记录触发时间
                period = (t[1] - t[0]) * hor_arr_list[hor_index]; // 计算周期
                frequency = 1000000 / period; // 计算频率
//                break;
            }
            cnt++;
        }

        if(sample_value[i] > V_max) V_max = sample_value[i]; // 统计最大值
        if(sample_value[i] < V_min) V_min = sample_value[i]; // 统计最小值
        if(cnt == 1)
        {
            scaled_value = sample_value[i] * 3.3 / 4095;
            rms_sum += scaled_value * scaled_value; // 统计有效值
        }
    }
    V_max = V_max * 3300 / 4095; // 计算最大值
    V_min = V_min * 3300 / 4095; // 计算最小值
    V_pp = V_max - V_min; // 计算峰峰值
    V_rms = sqrt(rms_sum / (t[1] - t[0])); // 计算有效值

    show_flag = 1;
//    HAL_TIM_Base_Start(&htim3);
}

void osc_process(int16_t num, KeyInfo info) {
    static SelectOption option;
    static int16_t ver_ratio = 800;
    static int16_t last_num = 0;

    if (show_flag) {
        show_flag = 0;

        // 处理按键
        if (info.state == KEY_SINGLE_CLICKED) {
            if (info.name == KEY_LEFT) {
                if (option == 0) option = 4;
                else option--;
            } else if (info.name == KEY_MIDDLE) {
                switch (option) {
                    case OPT_RUN_STATE:
                        run_state = !run_state;
                        break;
                    case OPT_TRIG_MODE:
                        trig_mode++;
                        if (trig_mode > 2) trig_mode = 0;
                        break;
                }
            } else if (info.name == KEY_RIGHT) {
                if (option == 4) option = 0;
                else option++;
            } else if (info.name == KEY_ENCODER) {
                switch (option) {
                    case OPT_VER:
                        ver_ratio = 800;
                        break;
                    case OPT_HOR:
                        hor_index = 2;
                        __HAL_TIM_SET_AUTORELOAD(&htim3, hor_arr_list[hor_index] - 1);
                        break;
                    case OPT_TRIG_LEVEL:
                        trig_level = 3500;
                        break;
                }
            }
        } else if (info.state == KEY_LONG_PRESSED && info.name == KEY_MIDDLE) {
            is_measure = !is_measure;
        }
        key_clear_flags();

        // 处理滚轮
        num /= 4;
        if (num != last_num) {
            int16_t step = num - last_num;
            last_num = num;
            switch (option) {
                case OPT_RUN_STATE:
                    break;
                case OPT_TRIG_MODE:
                    break;
                case OPT_VER:
                    ver_ratio += step * 100;
                    if (ver_ratio < 600) ver_ratio = 600;
                    else if (ver_ratio > 2000) ver_ratio = 2000;
                    break;
                case OPT_HOR:
                    hor_index += step;
                    if (hor_index < 0) hor_index = 0;
                    else if (hor_index > 6) hor_index = 6;
                    __HAL_TIM_SET_AUTORELOAD(&htim3, hor_arr_list[hor_index] - 1);
                    break;
                case OPT_TRIG_LEVEL:
                    trig_level += step * 100;
                    if (trig_level < 0) trig_level = 0;
                    else if (trig_level > 4095) trig_level = 4095;
                    break;
            }
        }

        // 复制需要显示的点
        for (int i = 0; i < show_points_num; i++) {
            show_value[i] = sample_value[i + hor_pos + trig_pos] * 3300 * 10 / 4096 / ver_ratio;
        }

        show_trig_level_mV = trig_level * 3300 / 4096;
        show_trig_level = show_trig_level_mV * 10 / ver_ratio;

        // 绘制UI
        if (!is_measure) {
            if (run_state == OSC_RUN) {
                gui_main_interface(show_value, show_points_num, run_state, trig_mode, ver_ratio,
                                   hor_arr_list[hor_index] * 10, show_trig_level, show_trig_level_mV, option);
                for (int i = 0; i < show_points_num; i++) { // 复制暂停点
                    stop_show_value[i] = show_value[i];
                }
                if (show_normal_flag) {
                    show_normal_flag = 0;
                    run_state = OSC_STOP;
                }
            }
            if (run_state == OSC_STOP) {
                gui_main_interface(stop_show_value, show_points_num, run_state, trig_mode, ver_ratio,
                                   hor_arr_list[hor_index] * 10, show_trig_level, show_trig_level_mV, option);
            }
        } else {
            gui_measure(show_value, show_points_num, period, frequency, V_max, V_min, V_pp, V_rms);
        }

//        gui_test_input(num, direction, info);
        // 继续运行

        HAL_TIM_Base_Start(&htim3);
    }
}

